from django.db import models
from django.db.models.options import Options
from django.db.models.signals import class_prepared

from django.utils.functional import curry

from django.core.urlresolvers import reverse
@property
def ordering_url_property(self):
	opts = self._meta
	return reverse('ordering.views.order', args=[opts.app_label, opts.object_name.lower(), self.pk])

def update_prepared_class(sender, **kwargs):
	if sender._meta.orderable:
		sender.add_to_class('admin_ordering', models.IntegerField('Order', default=curry(set_max_order, sender), editable=False))
		sender.add_to_class('ordering_url', ordering_url_property)

class_prepared.connect(update_prepared_class)

def set_max_order(model):
	try:
		return model.objects.order_by('-admin_ordering')[0].admin_ordering + 1
	except IndexError:
		return 1

def add_ordering_support(fn):
	def wrapper(self, cls, name):
		cls.orderable = self.orderable = self.meta and self.meta.__dict__.pop('orderable', False)
		if cls.orderable:
			# Orderable models must use `admin_ordering` as order field only
			if hasattr(self.meta, 'ordering'):
				from django.core.exceptions import ImproperlyConfigured
				raise ImproperlyConfigured('Orderable models can not have "ordering" option.')
			self.meta.ordering = ('admin_ordering',)
		fn(self, cls, name)
	return wrapper

Options.contribute_to_class = add_ordering_support(Options.contribute_to_class)